package com.sprites;

import com.bricks2break.Player;
import com.bricks2break.Statics;

import sheep.collision.CollisionListener;
import sheep.game.Sprite;

public class Ball extends Sprite implements CollisionListener {
	private int width, height;
	private Player currentOwner;

	/**
	 * Ball class constructor
	 * 
	 * @param position
	 *            the y position of the ball
	 */
	public Ball(float position) {
		super(Statics.image_ball);
		this.height = (int) Statics.image_ball.getHeight();
		this.width = (int) Statics.image_ball.getWidth();
		addCollisionListener(this);
		setGroup((int) Statics.COLLISION_GROUP);
		setPosition(Statics.SCREEN_WIDTH / 2, position);

		// Set up speed with a small random element
		if (position == Statics.POSITION_BRICK_SPAWN_BOTTOM) {
			if (Math.random() < 0.5) {
				setSpeed((float) (0.7 * Statics.DEFAULT_BALL_SPEED_X + (Math.random() * Statics.DEFAULT_BALL_SPEED_X * 0.6)), Statics.DEFAULT_BALL_SPEED_Y);
			} else {
				setSpeed((float) (-0.7 * Statics.DEFAULT_BALL_SPEED_X - (Math.random() * Statics.DEFAULT_BALL_SPEED_X * 0.6)), Statics.DEFAULT_BALL_SPEED_Y);
			}
		} else {
			if (Math.random() < 0.5) {
				setSpeed((float) (0.7 * Statics.DEFAULT_BALL_SPEED_X + (Math.random() * Statics.DEFAULT_BALL_SPEED_X * 0.6)), -Statics.DEFAULT_BALL_SPEED_Y);
			} else {
				setSpeed((float) (-0.7 * Statics.DEFAULT_BALL_SPEED_X - (Math.random() * Statics.DEFAULT_BALL_SPEED_X * 0.6)), -Statics.DEFAULT_BALL_SPEED_Y);
			}
		}
		currentOwner = null;
	}

	public void setCurrentOwner(Player p) {
		currentOwner = p;
	}

	public Player getCurrentOwner() {
		return currentOwner;
	}

	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

	/**
	 * Update method
	 */
	@Override
	public void update(float dt) {
		// Check outside screen east, set speed west
		if (getX() >= Statics.SCREEN_WIDTH - width / 2 && getSpeed().getX() > 0) {
			setSpeed(-Math.abs(getSpeed().getX()), getSpeed().getY());
		}

		// Check outside screen west, set speed east
		if (getX() <= width / 2 && getSpeed().getX() < 0) {
			setSpeed(Math.abs(getSpeed().getX()), getSpeed().getY());
		}

		// Check outside screen bottom, set ball to top player
		if (getY() >= Statics.SCREEN_HEIGHT + height / 2 && getSpeed().getY() > 0) {
			setSpeed(getSpeed().getX(), -Math.abs(getSpeed().getY()));
			setPosition(getPosition().getX(), Statics.POSITION_BRICK_SPAWN_TOP);
			currentOwner = Statics.level.getTopPlayer();
		}

		// Check outside screen top, set ball to bottom player
		if (getY() <= -height / 2 && getSpeed().getY() < 0) {
			setSpeed(getSpeed().getX(), Math.abs(getSpeed().getY()));
			setPosition(getPosition().getX(), Statics.POSITION_BRICK_SPAWN_BOTTOM);
			currentOwner = Statics.level.getBottomPlayer();
		}
		super.update(dt);
	}

	/**
	 * Method that checks collisions with the ball
	 */
	public void collided(Sprite a, Sprite b) {
		// set up variables for easy access
		float bHeight, bWidth;//

		// check if collisions is with a brick
		if (b instanceof Brick) {
			bHeight = ((Brick) b).getHeight() / 2;
			bWidth = ((Brick) b).getWidth() / 2;
		}
		// check if collisions is with a paddle
		else if (b instanceof Paddle) {
			bHeight = ((Paddle) b).getHeight() / 2;
			bWidth = ((Paddle) b).getWidth() / 2;
			// set direction to right if ball hits right end of paddle,
			// set to left if ball hits the left end
			float tempDx = ((Paddle) b).getX() - getX();
			float minDx = ((Paddle) b).getWidth() / 2 - Statics.PADDLE_DIRECTIONAL_BOUNCE_AREA;
			if (Math.abs(tempDx) > minDx) {
				if (tempDx < 0) {
					// right side
					setSpeed(Math.abs(getSpeed().getX()), getSpeed().getY());
				} else {
					// left side
					setSpeed(-Math.abs(getSpeed().getX()), getSpeed().getY());
				}

			}

		}
		// check if collisions is with a ball
		else if (b instanceof Ball) {
			bHeight = ((Ball) b).getHeight() / 2;
			bWidth = ((Ball) b).getWidth() / 2;
		}
		// else unknown collisions
		else {
			System.out.println("Unknown collision");
			return;
		}

		// check the direction of the collision
		float[] dir = new float[4];
		dir[0] = Math.abs((getPosition().getX() - getWidth() / 2) - (b.getPosition().getX() + bWidth));// left
		dir[1] = Math.abs((getPosition().getX() + getWidth() / 2) - (b.getPosition().getX() - bWidth));// right
		dir[2] = Math.abs((getPosition().getY() - getHeight() / 2) - (b.getPosition().getY() + bHeight));// over
		dir[3] = Math.abs((getPosition().getY() + getHeight() / 2) - (b.getPosition().getY() - bHeight));// under

		// find smallest difference(this will be the correct direction to bounce
		// the ball inn)
		int min = 0;
		for (int i = 1; i < dir.length; i++) {
			if (dir[i] < dir[min]) {
				min = i;
			}
		}

		// set new direction
		switch (min) {
		case 0:
			a.setSpeed(Math.abs(a.getSpeed().getX()), a.getSpeed().getY());
			break;
		case 1:
			a.setSpeed(-Math.abs(a.getSpeed().getX()), a.getSpeed().getY());
			break;
		case 2:
			a.setSpeed(a.getSpeed().getX(), Math.abs(a.getSpeed().getY()));
			break;
		case 3:
			a.setSpeed(a.getSpeed().getX(), -Math.abs(a.getSpeed().getY()));
			break;
		}
	}
}